package com.ylsdxy.auth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;

//客户端认证服务
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    //配置客户端信息
    @Resource
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//        clients.inMemory()
//                .withClient("woniuxy")//客户端账号
//                .secret(bCryptPasswordEncoder.encode("123"))//密码
//                .scopes("all")//授权范围：能获得到用户的哪些数据，如头像、账户密码
//                .authorizedGrantTypes("authorization_code","password","refresh_token")//认证方式   "authorization_code" 验证码模式 "password"密码模式
//                .redirectUris("http://woniuxy.com");//接受授权码的接口  第三方应用的接口
        clients.withClientDetails(clientDetailsService);
    }
    @Bean
    public ClientDetailsService clientDetailsService(DataSource dataSource) {
        //在数据库中去获取客户端信息（oauth_client_details表）
        return new JdbcClientDetailsService(dataSource);
    }

    @Resource
    private AuthenticationManager authenticationManager;
    //开启密码模式
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .tokenServices(tokenServices());
    }
//    jwy相关依赖
    @Resource
    private TokenStore tokenStore;
    @Resource
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    @Resource
    private ClientDetailsService clientDetailsService;

    // 配置token、refreshtoken相关
    private AuthorizationServerTokenServices tokenServices(){
        // 创建服务对象
        DefaultTokenServices services = new DefaultTokenServices();
        // 设置客户端详情服务
        services.setClientDetailsService(clientDetailsService);
        // 支持刷新令牌
        services.setSupportRefreshToken(true);
        // 不重复使用refreshtoken，每次刷新之后只能用新的refreshtoken才能继续刷新
        services.setReuseRefreshToken(false);
        // 设置令牌存储策略
        services.setTokenStore(tokenStore);

        // 设置令牌增强
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
        services.setTokenEnhancer(tokenEnhancerChain);

        // 设置令牌过期时间
        services.setAccessTokenValiditySeconds(600);
        services.setRefreshTokenValiditySeconds(6000);

        return services;
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        // 默认是denyAll()：拒绝所有
        oauthServer.checkTokenAccess("permitAll()");
    }
}
